
#include "jncDefs.h"
#include "jncTypeConversion.h"

// Verify if conversion is possible
// to type T or it's signed or unsigned version
template<class T, class T1, class T2>
int convertible(jncTypev& v) {
  try 
    {
      return *(boost::any_cast<T*>(v));
    }
  catch(boost::bad_any_cast&) 
    {
      try 
	{
	  return *(boost::any_cast<T1*>(v));
	}
      catch(boost::bad_any_cast&) 
	{
	  try 
	    {
	      return *(boost::any_cast<T2*>(v));
	    } 
	  catch(boost::bad_any_cast&) 
	    {
	      return -1;
	    }
	}
    }
}

// Try to get a valid digit
int numberConv(jncTypev& v) {
  int i;
  if((i = convertible<short, unsigned short, signed short>(v)) == -1)
    if((i = convertible<int, unsigned int, signed int>(v)) == -1)
      if((i = convertible<long, unsigned long, signed long>(v)) == -1)
	return -1;
  return i;
  // convertible<double>(v); // TODO: No double type supported
}


#define PBCONV(z, n, data)						\
  BOOST_PP_EXPR_IF(BOOST_PP_SUB(BOOST_PP_SEQ_SIZE(BOOST_PP_SEQ_ELEM(n, data)), 1), SELF BOOST_PP_SEQ_TAIL(BOOST_PP_SEQ_ELEM(n, data))& BOOST_PP_SEQ_HEAD(BOOST_PP_SEQ_ELEM(n, data))(jncTypev& v){return castTo<SELF BOOST_PP_SEQ_TAIL(BOOST_PP_SEQ_ELEM(n, data))>(v);})

#define ACONV(z, n, data)			\
  BOOST_PP_EXPR_IF(BOOST_PP_SUB(BOOST_PP_SEQ_SIZE(BOOST_PP_SEQ_ELEM(n, data)), 1), SELF BOOST_PP_SEQ_TAIL(BOOST_PP_SEQ_ELEM(n, data))& BOOST_PP_SEQ_HEAD(BOOST_PP_SEQ_ELEM(n, data))(jncTypev& v){return castArray<SELF BOOST_PP_SEQ_TAIL(BOOST_PP_SEQ_ELEM(n, data))>(v);})

BOOST_PP_REPEAT(BOOST_PP_SEQ_SIZE(BLOCAL), PBCONV, BLOCAL) // for Basic
  BOOST_PP_REPEAT(BOOST_PP_SEQ_SIZE(PLOCAL), PBCONV, PLOCAL) // for pointer 
  BOOST_PP_REPEAT(BOOST_PP_SEQ_SIZE(ALOCAL), PBCONV, ALOCAL) // for array
